package com.coder.books.thinkinjava.concurrency;

import com.coder.util.CollectionData;
import com.coder.util.CountingGenerator;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 *
 * @author yuhushuan
 * @date 2020/9/6 21:52
 */
abstract class ListTest extends Tester<List<Integer>> {

    ListTest(String testId, int nReaders, int nWriters) {
        super(testId, nReaders, nWriters);
    }

    class Reader extends TestTask {
        long result = 0;

        @Override
        void test() {
            for (long i = 0; i < testCycles; i++) {
                for (int index = 0; index < containerSize; index++) {
                    result += testContainer.get(index);
                }
            }
        }

        @Override
        void putResults() {
            readResult += result;
            readTime += duration;
        }
    }

    class Writer extends TestTask {

        @Override
        void test() {
            for (long i = 0; i < testCycles; i++) {
                for (int index = 0; index < containerSize; index++) {
                    testContainer.set(index, writeData[index]);
                }
            }
        }

        @Override
        void putResults() {
            writeTime += duration;
        }
    }

    @Override
    void startReadersAndWriters() {
        for (int i = 0; i < nReaders; i++) {
            exec.execute(new Reader());
        }
        for (int i = 0; i < nWriters; i++) {
            exec.execute(new Writer());
        }
    }

    static class SynchronizedArrayListTest extends ListTest {

        SynchronizedArrayListTest(int nReaders, int nWriters) {
            super("Synched ArrayList", nReaders, nWriters);
        }

        @Override
        List<Integer> containerInitializer() {
            return Collections.synchronizedList(CollectionData.list(new CountingGenerator.Integer(), containerSize));

        }
    }

    static class CopyOnWriterArrayListTest extends ListTest {

        CopyOnWriterArrayListTest(int nReaders, int nWriters) {
            super("CopyOnWriteArrayList", nReaders, nWriters);
        }

        @Override
        List<Integer> containerInitializer() {
            return new CopyOnWriteArrayList<>(
                    CollectionData.list(new CountingGenerator.Integer(), containerSize));
        }
    }


}

public class ListComparisons {
    public static void main(String[] args) {
        Tester.initMain(args);
        new ListTest.SynchronizedArrayListTest(10, 0);
        new ListTest.SynchronizedArrayListTest(9, 1);
        new ListTest.SynchronizedArrayListTest(5, 5);

        new ListTest.CopyOnWriterArrayListTest(10, 0);
        new ListTest.CopyOnWriterArrayListTest(9, 1);
        new ListTest.CopyOnWriterArrayListTest(5, 5);

        Tester.exec.shutdown();
    }
}
